package jam.network.message;

import jam.network.ClientController;

import java.util.*;

//
// =============================================================================
//

/**
 * A class that parses network messages.
 */
public class MessageParser {
    /**
     * Creates and returns the appropriate concrete message class based on the
     * keyword.
     *
     * @param data The raw network message string.
     * @return A concrete message object.
     */
    public static void parseMessage(String data, ClientController controller) {
        Scanner s = new Scanner(data); s.useDelimiter(":");
        
        // Try scan the received data.
        String keyword;
        int transactionId;
        try {
            keyword = s.next();
            transactionId = s.nextInt();
        } catch (Exception e) {
            System.out.println(e.toString());
            return;
        }

        // Check pings!
        if (keyword.equalsIgnoreCase(ServerActionPing.KEYWORD)) {
            processResponse(controller, new ClientResponse(transactionId, keyword, s));
            return;
        }
        
        // Send an immediate fail if we're not logged in.
        if (controller.getModel().isLoggedIn() == false) {
            if (keyword.equalsIgnoreCase(ClientActionLogin.KEYWORD))
                processCommand(controller, new ClientActionLogin(transactionId, s)); 
            else
                controller.send(new ServerResponse(transactionId, keyword, false));
                
            return;
        }
        
        // All of these require valid logins.
        if (keyword.equalsIgnoreCase(ClientActionMessage.KEYWORD))
            processCommand(controller, new ClientActionMessage(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionJoin.KEYWORD))
            processCommand(controller, new ClientActionJoin(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionLeave.KEYWORD))
            processCommand(controller, new ClientActionLeave(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionLock.KEYWORD))
            processCommand(controller, new ClientActionLock(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionInvite.KEYWORD))
            processCommand(controller, new ClientActionInvite(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionLogout.KEYWORD))
            processCommand(controller, new ClientActionLogout(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionPassword.KEYWORD))
            processCommand(controller, new ClientActionPassword(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionRegister.KEYWORD))
            processCommand(controller, new ClientActionRegister(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionAddCC.KEYWORD))
            processCommand(controller, new ClientActionAddCC(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionRemoveCC.KEYWORD))
            processCommand(controller, new ClientActionRemoveCC(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionAddUC.KEYWORD))
	    processCommand(controller, new ClientActionAddUC(transactionId, s));
	else if (keyword.equalsIgnoreCase(ClientActionRemoveUC.KEYWORD))
	    processCommand(controller, new ClientActionRemoveUC(transactionId, s));
	else if (keyword.equalsIgnoreCase(ClientRequestChannelUserList.KEYWORD))
            processCommand(controller, new ClientRequestChannelUserList(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientRequestUserInfo.KEYWORD))
            processCommand(controller, new ClientRequestUserInfo(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientRequestGetUserContacts.KEYWORD))
            processCommand(controller, new ClientRequestGetUserContacts(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientRequestGetChannelContacts.KEYWORD))
            processCommand(controller, new ClientRequestGetChannelContacts(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientRequestGetAvatar.KEYWORD))
            processCommand(controller, new ClientRequestGetAvatar(transactionId, s));
        else if (keyword.equalsIgnoreCase(ClientActionUploadAvatar.KEYWORD))
            processCommand(controller, new ClientActionUploadAvatar(transactionId, s));
        else if (keyword.equalsIgnoreCase(ServerActionMessage.KEYWORD) ||
            keyword.equalsIgnoreCase(ServerActionJoin.KEYWORD) ||
            keyword.equalsIgnoreCase(ServerActionInvite.KEYWORD) ||
            keyword.equalsIgnoreCase(ServerActionLeave.KEYWORD))
            processResponse(controller, new ClientResponse(transactionId, keyword, s));
    }
    
    private static void processCommand(ClientController controller, ClientCommand command) {
        if (command != null)
            try {
                command.process(controller);
            } catch (Exception e) {
                System.out.println(e);
            }
    }
    
    private static void processResponse(ClientController controller, ClientResponse response) {
        if (response == null)
            return;
            
        ServerCommand message = controller.removeAwaiting(response.getTransactionId());
        if (message != null)
            try {
                message.process(controller, response);
            } catch (Exception e) {
                System.out.println(e);
            }
    }
}
